//
//  JYRouterManager.swift
//  JYRouter
//
//  Created by huangguojian on 2022/6/9.
//

import UIKit

/// 路由管理器协议
public protocol JYRouterManager {
    associatedtype ModuleKey: Hashable
    
    /// 配置每个模块对应的路有
    static var config: [ModuleKey: JYRouterProtocol.Type] { get }
    
    /// 白名单的类型
    static var whiteList: JYRouterWhiteList { get }
    
    ///当前的tabbarController
    static var currentTabBarController: UITabBarController { get }
    
    ///当前的NavigationController
    static var currentNavigationController: UINavigationController { get }
    
    /// 处理非路由白名单的链接
    static func handleNotOnWhiteList(_ urlStr: String)
    
    /// 通过链接的 host 获取模块
    static func getModule(from host: String) -> ModuleKey?
    
    /// 解析链接, 获取路由
    static func getRouter(from urlStr: String) throws -> JYRouterProtocol
    
    /// 展示 tabbar 并选中 对应的 controller
    static func showTabbarControllerAndSelect(controller: JYRoutable, animated: Bool)
}

public extension JYRouterManager {
    
    ///通过字符串链接push跳转
    static func linkUrl(_ link: String, animated: Bool = true, callBack: @escaping (JYRouterModelType) -> Void = { _ in }) {
        
        //解析链接，按规则生成字典
        do {
            let router = try getRouter(from: link.trimmingCharacters(in: .whitespacesAndNewlines))
            router.link(by: Self.self, animated: animated, callBack: callBack)
        } catch JYRouterError.invalidUrl(let urlStr) {
            print("无效链接 -> \(urlStr)")
        } catch JYRouterError.notMatchRouter {
            print("没有匹配的路由")
        } catch JYRouterError.notOnTheWhiteList(let urlStr) {
            print("非白名单路由 -> \(urlStr)")
            handleNotOnWhiteList(urlStr)
        } catch {
            print("反序列化失败 -> \(link)")
        }
    }
    
    static func getRouter(from urlStr: String) throws -> JYRouterProtocol {
        
        /* 解析链路 url , 合成[Path: QueryItems]的字典
         * 例子 app://host/path?a=1&b=2 --> [path: ["a": "1", "b": "2"]]
         */
        
        guard let routerUrl = urlStr.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
              let components = URLComponents(string: routerUrl),
              let scheme = components.scheme else { throw JYRouterError.invalidUrl(url: urlStr) }
        
        // 路由白名单校验
        switch whiteList {
        case .unlimited: break
        case .contain(let schemes):
            if !schemes.contains(scheme) { throw JYRouterError.notOnTheWhiteList(url: urlStr) }
        }
        
        guard let module = getModule(from: components.host ?? ""),
              let routerType = config[module] else { throw JYRouterError.notMatchRouter }
        
        let rootKey = components.path.replacingOccurrences(of: "/", with: "")
        let params = components.queryItems?.reduce(into: [String: String](), { $0[$1.name] = $1.value }) ?? [:]
        let routerDic: [String: [String: String]] = [rootKey: params]
        
        let routerData = try JSONSerialization.data(withJSONObject: routerDic)
        return try routerType.decode(from: routerData)
    }
    
    ///获取App启动时Window的rootViewController
    static func getAppRootController() -> UIViewController {
        
        let window = UIApplication.shared.delegate?.window
        
        let rootController = window??.rootViewController
        
        return rootController!
    }
}
